#include "main.h"
#include "cmsis_os.h"
#include "lora.h"
#include "radio.h"
#include "string.h"
#include "param.h"
#include "userModbus.h"
#include "common.h"
#include "swInfo.h"

#define INFO_MODE_REPORT	0X04
#define	INFO_MODE_CHECK		0X83

typedef struct
{
	uint8_t buf[70];
	uint8_t len;
}tloraSendMes;

osMailQDef(loraSendMail,5, tloraSendMes); // 创建lora发送邮箱队列
osMailQId  loraSendMail;
tRadioDriver *radio;
uint8_t radioChChange=0;

struct
{
	uint8_t buffer[128];
	uint16_t size;
}loraRx;

void lora_init()
{
	loraSendMail = osMailCreate(osMailQ(loraSendMail), NULL);      // create mail queue
	radio = RadioDriverInit( );
	radio->Init();
	radio->StartRx();	
	radioChChange=0;
}
//设置lora无线信道标志改变标志
void lora_chChange()
{
	radioChChange=1;
}
uint8_t lora_putSendQueue(uint8_t *buf,uint8_t len)
{
  tloraSendMes *pmes;
	pmes=osMailAlloc(loraSendMail, 0);
	if(pmes==NULL)return 0;
	pmes->len=len; 
	memcpy(pmes->buf,buf,len);
	osMailPut(loraSendMail,pmes);	
	return 1;
}
uint8_t lora_cmd_getParam()
{
	uint8_t checkValue=0x00;
  tloraSendMes *pmes;
	pmes=osMailAlloc(loraSendMail, 0);
	if(pmes==NULL)return 0;
	pmes->len=0;
	pmes->buf[pmes->len++]=0x7E;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()>>8;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()&0xff;
	pmes->buf[pmes->len++]=param_get_nodeAdd();
	pmes->buf[pmes->len++]=0x81;
	pmes->buf[pmes->len++]=11; //长度
	pmes->buf[pmes->len++]=0x00;//辅助标记
	//info
	param_get(pmes->buf+pmes->len);
	pmes->len+=10;
	
	checkValue=com_getCheckSum(pmes->buf+1,pmes->len-1);//计算累加和
	pmes->buf[pmes->len++]=checkValue;//累加和
	pmes->buf[pmes->len++]=0x0D;//结尾符号	
	
	osMailPut(loraSendMail,pmes);
	return 1;
}
uint8_t lora_cmd_setParam(uint8_t *rbuf,uint8_t len)
{
	uint8_t checkValue=0x00;
	tloraSendMes *pmes;
	pmes=osMailAlloc(loraSendMail, 0);
	if(pmes==NULL)return 0;
	param_set(rbuf+7);   //指向信息域的网络地址
	pmes->len=0;
	pmes->buf[pmes->len++]=0x7E;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()>>8;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()&0xff;
	pmes->buf[pmes->len++]=param_get_nodeAdd();
	pmes->buf[pmes->len++]=0x82;
	pmes->buf[pmes->len++]=0x02;//长度
	pmes->buf[pmes->len++]=0x00;//辅助标记
	pmes->buf[pmes->len++]=0;//正常返回
	checkValue=com_getCheckSum(pmes->buf+1,pmes->len-1);//计算累加和
	pmes->buf[pmes->len++]=checkValue;//累加和
	pmes->buf[pmes->len++]=0x0D;//结尾符号
	
	osMailPut(loraSendMail,pmes);
	return 1;
}

uint8_t lora_cmd_Info(uint8_t swAdd,uint8_t mode)
{
	uint8_t sw_num; //开关路数
	uint8_t checkValue=0x00;
	uint32_t tmp=0;
	tloraSendMes *pmes;
	pmes=osMailAlloc(loraSendMail, 0);
	if(pmes==NULL)return 0;
	
	pmes->len=0;
	pmes->buf[pmes->len++]=0x7E;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()>>8;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()&0xff;
	pmes->buf[pmes->len++]=param_get_nodeAdd();
	pmes->buf[pmes->len++]=mode;  //根据是查询获取信息还是主动上报信息设置LORA命令码
	pmes->buf[pmes->len++]=54;//长度
	pmes->buf[pmes->len++]=0x00;//辅助标记
	pmes->buf[pmes->len++]=swinfo_get_number();			//开关路数
	sw_num=swinfo_get_number();
	//远控标志
	tmp=swinfo_get_conflag();		
	pmes->buf[pmes->len++]=tmp>>16;
	pmes->buf[pmes->len++]=tmp>>8;
	pmes->buf[pmes->len++]=tmp;
	//开关分合闸状态
	uint8_t mask=0x00; //把不相关的位给屏蔽了
	for(uint8_t i=0;i<sw_num;i++)
	{
			mask|=1<<i;
	}
	tmp=swinfo_get_state()&mask;
	//tmp=swinfo_get_conflag();		
	pmes->buf[pmes->len++]=tmp>>16;
	pmes->buf[pmes->len++]=tmp>>8;
	pmes->buf[pmes->len++]=tmp;
	//起始开关地址
	pmes->buf[pmes->len++]=swAdd;
	//开关信息，共44bytes
	swinfo_get_info(swAdd,pmes->buf+pmes->len);
	pmes->len+=SW_INFO_BYTES;
	//附加信息
	pmes->buf[pmes->len++]=swinfo_get_extras();
	//计算累加和
	checkValue=com_getCheckSum(pmes->buf+1,pmes->len-1);
	pmes->buf[pmes->len++]=checkValue;
	//结尾符号
	pmes->buf[pmes->len++]=0x0D;
	
	osMailPut(loraSendMail,pmes);
	return 1;	
}
uint8_t lora_cmd_setSwitch(uint8_t *rbuf,uint8_t len)
{
	uint8_t allCh=0x00; 		//开关路数
	uint8_t err=0;					//错误标记
	uint8_t conBytes=0x00;	//控制标志、分合闸控制字节数
	uint32_t conFlag=0x00;	//远程控制标志，需要根据协议进行拼成一个32bit的数据
	uint32_t conValue=0x00;	//合关闸控制数据，需要根据协议进行拼接成一个32bit的数据
	uint8_t checkValue=0x00;//
	tloraSendMes *pmes;
	if(len!=17)return 0;    //
	
	allCh=rbuf[7];//获取控制开关路数
	//conBytes=(rbuf[5]-3)/2; //(消息长度-3)/2
//	if((conBytes*8)<allCh)  
//	{
//		err=1;
//	}
//	else
//	{
//		for(uint8_t i=0;i<conBytes;i++)
//		{
//			conFlag+=(rbuf[8+i]<<(conBytes-i-1)*8); //把远程控制标志进行拼接
//			conValue+=(rbuf[8+conBytes+i]<<(conBytes-i-1)*8); //把远程控制标志进行拼接
//		}
		conFlag=(rbuf[8]<<16)+(rbuf[9]<<8)+rbuf[10];
		conValue=(rbuf[11]<<16)+(rbuf[12]<<8)+rbuf[13];
		for(uint8_t i=0;i<allCh;i++)
		{
			if(conFlag&(1<<i))  //bit为1表示对开关进行远程控制
			{
				umb_setOneSw(i,conValue&(1<<i));//通过modbus控制开关分合
			}
		}	
//	}
	
	
	pmes=osMailAlloc(loraSendMail, 0);
	if(pmes==NULL)return 0;
	
	pmes->len=0;
	pmes->buf[pmes->len++]=0x7E;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()>>8;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()&0xff;
	pmes->buf[pmes->len++]=param_get_nodeAdd();
	pmes->buf[pmes->len++]=0x85;
	pmes->buf[pmes->len++]=1; //长度
	pmes->buf[pmes->len++]=0x00;//辅助标记
	pmes->buf[pmes->len++]=err; //正常返回0,错误返回1
	checkValue=com_getCheckSum(pmes->buf+1,pmes->len-1);//计算累加和
	pmes->buf[pmes->len++]=checkValue;//累加和
	pmes->buf[pmes->len++]=0x0D;//结尾符号		
	osMailPut(loraSendMail,pmes);
	return 1;
}
//lora到485透传发送
void lora_cmd_passThrough(uint8_t *rbuf,uint8_t len)
{
	uint8_t dlen=rbuf[5]-2;
	umb_putSendQueue(rbuf[6],rbuf[7],rbuf+8,dlen,1);
}
//透传应答回给lora
uint8_t lora_cmd_AckPassThrogh(uint8_t *buf,uint8_t len)
{
	uint8_t checkValue=0x00;
  tloraSendMes *pmes;
	if(pmes==NULL)return 0;
	
	pmes=osMailAlloc(loraSendMail, 0);
	pmes->len=0;
	pmes->buf[pmes->len++]=0x7E;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()>>8;
	pmes->buf[pmes->len++]=param_get_gatewayAdd()&0xff;
	pmes->buf[pmes->len++]=param_get_nodeAdd();
	pmes->buf[pmes->len++]=0x86;
	pmes->buf[pmes->len++]=len; //长度
	memcpy(pmes->buf+pmes->len,buf,len);
	pmes->len+=len;
	
	checkValue=com_getCheckSum(pmes->buf+1,pmes->len-1);//计算累加和
	pmes->buf[pmes->len++]=checkValue;//累加和
	pmes->buf[pmes->len++]=0x0D;//结尾符号		
	osMailPut(loraSendMail,pmes);
	
	return 1;
}
uint8_t lora_rxDeal(uint8_t *rbuf,uint8_t len)
{
	
	if(rbuf[3]!=param_get_nodeAdd())return 0; //节点地址不对，直接忽略不做处理
	if(com_getCheckSum(rbuf+1,len-3)!=rbuf[len-2])return 0;//判断校验和是否正确
	LEDD_TOGGLE();
	switch(rbuf[4])   //判断cmd
	{
		case LORA_CMD_GET_PARAM:
			lora_cmd_getParam();			
			break;
		case LORA_CMD_SET_PARAM:
			lora_cmd_setParam(rbuf,len);
			break;
		case LORA_CMD_GET_INFO:
			lora_cmd_Info(rbuf[7],INFO_MODE_CHECK);
			break;
		case LORA_CMD_UPLOAD_ACK:
			
			break;
		case LORA_CMD_SET_SWITCH:
			lora_cmd_setSwitch(rbuf,len);
			break;
		case LORA_CMD_PASSTHROUGH_SEND:
			lora_cmd_passThrough(rbuf,len);
			break;
	}
	return 1;
}
void lora_uploadPoll()
{
	static uint16_t counter;
	static uint8_t swCounter=0;
	
	uint8_t swAllNum=swinfo_get_number();
	uint16_t interval=param_get_dataInterval(); //获取上报周期
	counter++;
	//if(counter==(interval*1000+swCounter*50))
	if(counter==(5*1000+swCounter*50))
	{
		lora_cmd_Info(swCounter,INFO_MODE_REPORT);
		swCounter++;		
	}
	if(swCounter>=swAllNum)
	{
		swCounter=0;
		counter=0;
	}
}

void LoraTask(void const * argument)
{
	
  tloraSendMes  *pmes;
  osEvent  evt;
	uint16_t counter=0;  
  for(;;)
  {
		lora_uploadPoll();
		if(SX1276LoRaGetRFState()==RFLR_STATE_RX_RUNNING) //如果lora处在接收空闲状态
		{
			counter=0;
			evt = osMailGet(loraSendMail, 0);   // wait for mail
			if (evt.status == osEventMail)
			{
				pmes=evt.value.p;
				radio->SetTxPacket(pmes->buf,pmes->len);
				osMailFree(loraSendMail, pmes);
				LEDD_TOGGLE();
			}
		}
		else
		{
			counter++;
			if(counter>=200) //异常超时的话就重启lora进入接收状态
			{
				counter=0;
				radio->StartRx();
			}
		}
		
		switch(radio->Process())
		{
			case RF_RX_DONE:
				radio->GetRxPacket(loraRx.buffer,&loraRx.size);
				lora_rxDeal(loraRx.buffer,loraRx.size);							
				break;
			case RF_TX_DONE:  //发送完成会进入空闲状态
				radio->StartRx();
				break;
		}
		if(radioChChange)  //检查频率有改变，重新启动接收就可以重新配置频率
		{
			radioChChange=0;
			radio->StartRx();
		}
    osDelay(1);
  }
}
